package tichu_project252.View;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JLabel;
import javax.swing.JPanel;
import tichu_project252.CardClasses.Card;
import tichu_project252.Model.Model;
import tichu_project252.View.Buttons.ExitButton;
import tichu_project252.View.Buttons.NewGameButton;
import tichu_project252.View.Buttons.ScoreLabel;
import tichu_project252.View.Center.GrandTichuButton;
import tichu_project252.View.Center.ΤichuButton;
import tichu_project252.View.Player.CardContainer;
import tichu_project252.View.Player.PlayerPanel;

/**
 * This class implements the basic window of the game.
 *
 *
 * @see <a
 * href="http://docs.oracle.com/javase/6/docs/api/javax/swing/JFrame.html">JFrame</a>
 *
 * @author Alexandra Barka, ΑΜ: 2867, login : barka.
 * @version %I%, %G%
 */
public class GameFrame extends javax.swing.JFrame {

    private JPanel board = null;
    private Status status = null;
    private PlayerPanel[] player = null;
    private Center center = null;
    private Model m = null;
    private Image img = null;

    /**
     * Sets message in status message.
     *
     * <p><b>Precondition: </b> </p> <p><b>Postcondition: </b> Prints the new
     * message in the window. </p>
     *
     */
    public void setMessage(String s) {
        status.statusMessage.setText(s);
    }

    /**
     * This class implements the actionlistener this listener is used in a swing
     * timer. In order to implement the time delay of the grand tichu button
     * after the specified milliseconds, the listener performs the necessary
     * actions (e.g. disabling the grand tichu button, dealing the rest of the
     * cards and so on) *
     */
    class DisableGrandTichu implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            center.buttons.grandTichu.setEnabled(false); // disable the button
            try {
                m.deal(6); //deal the rest cards
            } catch (Exception ex) {
                Logger.getLogger(GameFrame.class.getName()).log(Level.SEVERE, null, ex);
            }
            for (int i = 0; i < 4; i++) {
                player[i].clear();
                try {
                    player[i].addAll(m.getPlayer(i).getCards());
                } catch (IOException ex) {
                    Logger.getLogger(GameFrame.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            m.setCurrent();
            enablePlayer(m.getCurrent());

            for (int i = 0; i < 4; i++) {
                player[i].checkBomb(); //check if player has bomb
            }
        }
    }

    /**
     *
     * Constructs The window of the game and sets the background image.
     *
     * <p><b>Constructor: </b>GameFrame(Model m) </p>
     *
     * <p><b>Precondition: </b> </p> <p><b>Postcondition: </b> Constructs a new
     * window </p>
     *
     * @param m The model
     * @throws IOException
     */
    public GameFrame(Model m) throws IOException {
        super("Tichu");
        this.m = m;

        img = Toolkit.getDefaultToolkit().createImage(this.getClass().getResource("/tichu_project252/Images/background.png"));
        System.out.println(img.toString());

        initComponents(img);

    }

    /**
     * Initializing and refreshing the graphics.
     *
     * @throws IOException
     */
    public void cleanup() throws IOException {
        initComponents(img);
        this.invalidate();
        this.validate();
    }
    
/**
 * Adds the cards to player discard pile.
 * Takes the cards and added to the pile of player i
 * 
 * @param temp The linked List with cards need to be transferred to the pie
 * @param i the number of the player
 * @throws IOException  if an error occured
 */
    public void addtoPile(LinkedList<Card> temp, int i) throws IOException {
        this.center.pile[i].addAll(temp);
    }

    public void setScore() {

        this.status.score.update(m.getScore(true), m.getScore(false));
    }
/**
 * Add the cards to center discard pile.
 * Adds the cards from the hand of player to the center pile.
 * 
 * @param temp The cards need to be taken in the middle
 * @throws IOException  if a mistake occure
 */
    public void addtoCenter(LinkedList<Card> temp) throws IOException {
        this.center.buttons.centerPile.addAll(temp);
    }
/**
 * Removes the cards from center pile.
 * Transformer(mutator)
 * 
 */
    public void clearCenterPile() {
        this.center.buttons.centerPile.clear();
    }
/**
 * Initialize all the components of the game.
 * Creates the players' card set layout and add the components too the window.
 * 
 * @param image The image of panel
 * @throws IOException if a mistake occurs
 */
    private void initComponents(Image image) throws IOException {

        status = new Status(m); //the status panel
        board = new JPanel(); //the board panel
        player = new PlayerPanel[4]; //the players panel 
        center = new Center(m);  //the center panel

        for (int i = 0; i < 4; i++) {
            player[i] = new PlayerPanel(m, i); //constructs the players panel
        }

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); //close operation of the window

        this.setContentPane(new ImagePanel(image));

        board.setLayout(new BorderLayout()); //the layout of the board

        //add the players to the board
        board.add(player[0], BorderLayout.NORTH);
        board.add(player[1], BorderLayout.EAST);
        board.add(player[2], BorderLayout.SOUTH);
        board.add(player[3], BorderLayout.WEST);
        board.add(center, BorderLayout.CENTER);

        board.setOpaque(false); 

        getContentPane().setLayout(new BorderLayout());
        this.getContentPane().add(status, BorderLayout.NORTH);
        this.getContentPane().add(board, BorderLayout.CENTER);


        javax.swing.Timer t = new javax.swing.Timer(4000, new DisableGrandTichu()); //the timer until grand tichu is disabled
        t.setRepeats(false);
        t.start();

        pack();
    }
/**
 * Enable the buttons to the current player.
 * 
 * If the player is not active he will not have the buttons activated.
 * 
 * @param i The player who must be active
 */
    public void enablePlayer(int i) {
        for (int j = 0; j < 4; j++) {
            this.player[j].setEnabled(false);
        }
        System.out.println("enable:" + i);

        this.player[i % 4].setEnabled(true);

    }

    /**
     * Implements the Jpanel where the discard piles of the players and
     * tichuButtons are.
     *
     */
    class Center extends JPanel {

        private CardContainer pile[] = null;
        private tichuButtons buttons = null;

        /**
         * Constucts the four piles of players and the tichuButtons described in
         * class below.
         *
         * <p><b>Constructor: </b> Center(Model m) </p>
         *
         * <p><b>Precondition: </b> </p> <p><b>Postcondition: </b> Constucts the
         * four piles of players and the tichuButtons described in class below.
         * </p>
         *
         * @param m The model
         * @throws IOException
         */
        public Center(Model m) throws IOException {
            pile = new CardContainer[4]; //the 4 piles of the players

            for (int i = 0; i < 4; i++) {
                pile[i] = new CardContainer(m, 2);
            }

            buttons = new tichuButtons(m); //the buttons in center

            this.setLayout(new BorderLayout()); //set the layout and add every component in right place
            this.add(pile[0], BorderLayout.NORTH);
            this.add(pile[1], BorderLayout.EAST);
            this.add(pile[2], BorderLayout.SOUTH);
            this.add(pile[3], BorderLayout.WEST);
            this.add(buttons, BorderLayout.CENTER);
            this.setOpaque(false); //no background for this component
        }

        /**
         * Returns the pile in position i .
         *
         * <p> <b> Accessor: </b> getPile() </p>
         *
         * <p><b> Precondition: </b> </p>
         *
         * </p> <p> <b> Postcondition:</b> Returns the discard pile of the player i. </p>
         *
         * @return The pile of the player i
         */
        
        public CardContainer getPile(int i) {
            return pile[i];
        }
/**
         * Returns the tichuButtons .
         *
         * <p> <b> Accessor: </b> getTichuButtons() </p>
         *
         * <p><b> Precondition: </b> </p>
         *
         * </p> <p> <b> Postcondition:</b> Returns the tichu Buttons. </p>
         *
         */
        public tichuButtons getTichuButtons() {
            return buttons;
        }
    }

    /**
     * Add the Tichu and Grand Tichu Button & the discard pile in center of the
     * table. We also define where the buttons should be.
     */
    class tichuButtons extends JPanel {

        private GrandTichuButton grandTichu = null;
        private ΤichuButton tichu = null;
        private CardContainer centerPile = null;

        /**
         * Constucts the tichu & grand tichu buttons and the discard pile in the
         * center. <p><b>Constructor: </b> tichuButtons(Model m) </p>
         *
         * <p><b>Precondition: </b> </p> <p><b>Postcondition: </b> Constucts the
         * tichu & grand tichu buttons and the discard pile in the center.</p>
         *
         * @param m The model
         * @throws IOException
         */
        public tichuButtons(Model m) throws IOException {
            super();

            this.grandTichu = new GrandTichuButton(m); //initialize the grand tichu button
            this.tichu = new ΤichuButton(m); // initialize the tichu button
            this.centerPile = new CardContainer(m, 2); //initialize the discard pile

            this.setLayout(new GridBagLayout()); //set the layout of the panel
            GridBagConstraints c = new GridBagConstraints();

            c.fill = GridBagConstraints.CENTER;
            c.weightx = 50;
            c.gridx = 0;
            c.gridy = 0;
            this.add(tichu, c); //add the tichu button to the panel

            c.weightx = 50;
            c.gridx = 1;
            c.gridy = 0;
            this.add(centerPile, c); //add the discard pile to the panel

            c.weightx = 50;
            c.gridx = 2;
            c.gridy = 0;
            this.add(grandTichu, c); //add the grand tichu button to the panel


            for (int i = 0; i < 4; i++) {
                tichu.setEnabled(!(m.getPlayer(i).getCards().size() == 14)); //if the players dont have 14 cards anymore disable the tichu button
            }

            this.setOpaque(false); // the background will be transparent
        }

        /**
         * Returns the discard pile in center .
         *
         * <p> <b> Accessor: </b> getCenterPile() </p>
         *
         * <p><b> Precondition: </b> </p>
         *
         * </p> <p> <b> Postcondition:</b> Returns the discard pile. </p>
         *
         * @return The discard pile in center
         */
        public CardContainer getCenterPile() {
            return this.centerPile;
        }
    }

    /**
     * Status class initialize and constructs the Buttons and the label. We also
     * define where the buttons will be and set the preffered size of the
     * components.
     */
    class Status extends JPanel {

        private ScoreLabel score = null; //score message
        private JLabel statusMessage = null; //player move message

        /**
         * Constucts the Status bar with new game, exit and score label and sets
         * where they will be.
         *
         * <p><b>Constructor: </b> Status(Model m) </p>
         *
         * <p><b>Precondition: </b> </p> <p><b>Postcondition: </b> Constucts the
         * Status bar with new game, exit and score label and sets where they
         * will be.</p>
         *
         * @param m The model
         */
        public Status(Model m) {
            super();

            score = new ScoreLabel(); //Initialize the score label
            statusMessage = new JLabel(""); //Initialize the status label
            this.setLayout(new GridBagLayout()); //set the layout of the component
            GridBagConstraints c = new GridBagConstraints();

            c.fill = GridBagConstraints.CENTER;
            c.weightx = 50;
            c.gridx = 0;
            c.gridy = 0;
            this.add(new NewGameButton(m), c); //add the New Game Button

            c.weightx = 50;
            c.gridx = 1;
            c.gridy = 0;
            this.add(score, c); //add the label of the score

            c.weightx = 50;
            c.gridx = 2;
            c.gridy = 0;
            this.add(new ExitButton(m), c); //add exit button

            c.weightx = 50;
            c.gridx = 1;
            c.gridy = 1;
            this.add(statusMessage, c); //add status message

            this.setPreferredSize(new Dimension(1000, 100));
        }
    }
}
